Hey there.
Welcome back.
In this lecture I want to talk about the difference between compile time, run time and logical errors
and how we can solve each of these errors, because you are guaranteed to run into each one of these
errors at some point in your code.
A compile time error is an error that is caused by syntax errors.
Remember, syntax is simply the grammar of your code before the scripts in our game can execute, our
computer has to compile or rewrite the code into a language that our computer can understand.
In this case, it has to rewrite our code into a bunch of zeros and ones.
Because our computers read information in binary.
During this compiling process, the compiler looks over the syntax or grammar of our code.
You can think of the compiler as an English teacher grading an essay you've written.
If the compiler spots a mistake, it immediately stops and spits out an error message into the console
saying, hey, you made a grammar mistake here and you need to fix it.
Compile time errors are super easy to fix, and we do not have to worry that much about debugging them
because the compiler will tell us exactly what is wrong.
So all we need to do is just read the error message, find the line where the error was encountered,
and fix our syntax error.
As you can see here, I forgot to fully spell out local.
And I also forgot to add an end statement to close out the scope of this function.
So when this script gets compiled and this code is attempting to be converted into binary, it's going
to immediately see these errors and notify us.
So I'm going to copy this code here.
And I'm going to paste it down here.
And first off, I'm going to keep this section commented out.
But I'm going to try and run this section of my code.
So if I hit run up here.
As you can see, we get our error.
Incomplete statement.
Expected assignment or a function call.
And that was on line 40in our script.
So if we go back we can think oh oops, I forgot to spell out local all the way.
There we go.
Fix that compile time error.
We can also demonstrate this one with the function if we go and try to execute this.
As you can see, we get our problem expected and to close the function.
So we needed that n statement to close the scope of the function.
But we did not add it.
And it said did you forget to close at line 43.
So if we go and check back oops, we forgot to close this function out.
So we can go ahead and add that end statement.
There we go.
We fixed our compile time error.
So compile time errors are really easy to spot.
The Lua linter, which checks over your code while you're typing it, will notify you when you have
an error.
Like when we forgot an end statement.
It's going to highlight all of this as red.
So compile time errors are really easy to fix and you shouldn't worry about them too much.
Now runtime errors are a little bit more involved because they happen after a script gets compiled and
it starts executing.
Runtime errors are not the result of bad grammar in our code, but they are the result of unexpected
conditions that we did not account for in our code.
Runtime errors still give us an error message, but it can take a little bit of time to figure out what
exactly is causing the problem.
A runtime error could be a problem, like trying to divide a number by zero, or attempting to access
an object in our game that does not exist in this function here.
I never created any index value pairs inside of some table, but I'm trying to grab the value there
and add another value to it.
I'm attempting to index this table with an index that does not exist, and add a number to it.
This is not going to error during the compile time of our script, but this will error when we go and
execute the script.
So as an example, if I copy this function and I place it down here in my code, we're going to run
into a problem.
Now the linter is automatically highlighting it for us.
And that's because I accidentally placed an equal sign there.
But there we go.
We're attempting to access the value at some table and add this other index to it, but that's going
to run into a problem.
Currently the linter is not underlining anything as red because our grammar looks good.
But when we go and execute this script, we're going to run into a problem.
So if we hit run here.
As you can see, we get our runtime error and we attempted to perform arithmetic on nil and a number.
So runtime errors are a little bit more involved.
We'll have to go to the line where the error originated from, which would be right here, and we'd
have to think through it and be like, oh, that's because I never added any index value pairs inside
of my table.
So I'm accessing a nil value and attempting to add a number to this nil value.
Oops.
Got to fix that.
Now, the last and most dreaded error in our code is the logical error.
Logical errors are the result of our own mistakes.
Syntactically, the code is correct and it does not get flagged by the compiler, and it does not get
flagged by the interpreter during runtime.
Instead, our code is executing fine, but it's producing a result that we did not expect or intend.
No error messages are given during a logical error, so it's up to us to try and figure out why the
logic in our code is bad.
As an example of a logical error, here we have an if statement that checks for whether or not a player
wants coffee or tea.
They say something, let's say, in the chat.
They say I want coffee, and then we check to see if they have a particular word inside of that string,
such as coffee.
If they say they want coffee, then oops, we're accidentally giving them tea.
Otherwise we're giving them coffee.
So this is not going to error at all.
Our code is going to execute just as we've written it out.
But the outcome of this code is not what we expect or intend.
We wanted to give the player a coffee, but instead we're accidentally giving them tea.
Logical errors are the most difficult errors to try and fix, especially in large projects, because
we can't really see what lines are being executed or flagged by our interpreter or compiler, like a
runtime or compile time error would.
Now, one way we could diagnose a runtime and logical errors are by using something called breakpoints
and print statements in our code.
We can use print statements as a triggering device that lets us know, hey, this section of code executed
okay, and if it didn't, I wouldn't have printed out this message into the console.
So, for example, if somebody wanted coffee, we could add different print statements in here to see
what exactly is executing.
And then based on the execution of those print statements, we could figure out, oh, oops, I'm accidentally
calling the wrong functions in these sections of the if statements.
Let me go ahead and flip those around and fix my logical error.
So just having print statements in your code allow you to see what section is being executed because
it'll appear in the console, and it'll help give you a better idea of what exactly is being executed
in your code.
We can also do the same thing with breakpoints, and a breakpoint is where we can mark a section in
our code where once the interpreter hits that mark, we stop the game and we hop back into the script
and we can go ahead and execute the code ourselves line by line, to see what exactly is happening.
Now, a great analogy to sum up all of these errors is to imagine yourself as a marathon runner.
A compile time error would be equivalent to you surveying a marathon course before attending it.
You check for any problems and check to see if there are any major hazards that can cause big injury
in the course.
If so, you flag those hazards before running in the race.
Now a runtime error would be equivalent to you verifying the course was safe and then running in the
marathon.
But then let's say all of a sudden the weather went bad and now you're in a thunderstorm and you get
struck by lightning.
The course track was okay, but we forgot to account for the external condition and variables that led
us to being struck by lightning.
The last type of error, a logical error, is when we account for all external conditions, and we found
the running track to be safe.
But let's say there's a fork in the running track, and we make the mistake and run down the wrong path
of the course.
Now we have ended up in an outcome that was unexpected.
We are lost and on the wrong trail, and that was our own fault.
So you should now know about the three types of errors in our code.
And we're going to learn about how to debug errors using breakpoints.
So to quickly demonstrate breakpoints here I'm just going to create a for loop that loops five times.
And I'm going to do in this for loop is just print out I into the console.
And then afterwards let's say we have some other random code.
And eventually there's an error in this code that we can't really understand what's happening.
I'm not going to make a super complex example, but to throw our own custom error, we can use the error
function, which allows us to send a message into the console and halts the thread of execution.
So I could say.
And here we encountered some error.
So once the interpreter goes through and executes and hits this point, it's going to halt the thread
and throw an error here.
Now to go ahead and use breakpoints.
What I'm going to do is insert one just before my for loop, and to do that we go to the line where
we would like to insert the breakpoint and we click right next to the number.
So if I click here we have now inserted this red dot which is our breakpoint.
If we no longer need this breakpoint, we can go ahead and right click it.
And we can go ahead and either disable it or delete this breakpoint.
But I want to keep this breakpoint here because I'm going to show you how we can use these breakpoints.
So when we go and run our game, immediately we have jumped into our script because the interpreter
has reached our breakpoint and is now telling us that we need to go ahead and manually go through the
script after our breakpoint.
So this yellow arrow signifies the next line of code we're about to execute.
And to use these breakpoints and debug our code, we go up to the debugger section here in the script
tag, and we have three buttons such as step into, step over, and step Out.
The step over button allows me to skip going into a function, in case I don't want to see how it is.
Run line by line and step out.
Lets me jump out of a function.
If I don't wish to see how the rest of the function executes.
So to continue executing through my code, I'm just going to keep pressing the step into button.
So we're going to hit step into.
We hit the print statement.
We're going to execute that print statement.
As you can see when printed into the console.
And then we're going to repeat this process in our loop.
And we're going to execute this for loop five times.
And eventually we hop out of that for loop and we move to our next line here, which is our error.
And then if we execute this line right here, there we go.
We encountered our error and we're done debugging.
So these breakpoints helped us to go line by line through our script and eventually understand where
exactly our error is coming from, and also understand what happened previous to that error occurring.
This was a fairly rough example, but you'll find breakpoints useful in more complex situations, especially
when you don't have a good idea of how your code is executing.
Now I'm just going to delete this breakpoint and we're going to go ahead and move on.
Because now I want to talk about how we can handle errors inside of our code.
There may be times when you have a piece of code that's going to error, and fixing that error is out
of your control.
As an example, there are dozens of functions in the Roblox API that are used to fetch information from
Roblox servers.
These functions are not guaranteed to succeed all the time due to external problems out of our control,
such as a server going down or some other event.
Because of this, these functions have the possibility of causing an error if they do error.
We do not want that error to halt the execution of our scripts.
This is where a function called pcall comes into play and its name is short for protected call.
So Pcall is a default function inside of Lua that allows us to handle a function.
And in case that function errors, instead of halting the threat of execution, it's going to return
a value of either true or false, telling us whether or not it's successfully executed.
The function.
And here it says runs the provided function and catches any error it throws, returning the function
success and its result.
So to demonstrate pcall we get to make two variables.
One I'm going to call success, and then to declare another variable on the same line, I'm going to
put a comma and I'm going to call this one result.
And it's going to be equal to our Pcall function, because our Pcall function is automatically going
to return a boolean of whether or not we were successful in executing the function that we passed to
the call function.
And then the result returns either the error message from that function, or any other values that get
returned from the function we pass to the call function.
So I'm going to put in here is a lambda function.
And a lambda function or an anonymous function is simply a function that has no identifier.
The purpose of this function.
Is just to execute here only.
And since there is no identifier, I can't type out the name and execute it elsewhere in my code.
It only exists right here.
So an anonymous function is simply one that has no identifier.
And inside of this lambda function, what I'm going to do is raise an error, and I'm just going to
say something like some error caught by call.
So when this p call function executes and it goes into execute this function, when this error is hit,
the call function is going to handle that.
And it's going to return false telling us that the function errored.
And then the result is going to be our error message.
So then we can go ahead and print success and result into the console, because the Pcall function is
going to prevent the main thread of execution from halting when this error is reached.
And I misspelled success here.
So let me fix that.
And now we can go ahead and run our script.
And there we go.
We get the value of false, which signifies that the function did not execute successfully.
And here we get our error message.
On line 41 we had some error caught by our pcall.
So this was just a quick lecture on the different errors in Lua and how we can handle those errors using
the Pcall function.
You reach the end of Lua basics, and now it is time to start interacting with our game and making fun
stuff in Roblox studio.
I will go ahead and see you in the next lecture.